package com.wuyan.web.form.helper.easyexcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.holder.ReadSheetHolder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 直接用map接收数据
 *
 * @author Jiaju Zhuang
 */
@Slf4j
public class NoModelDataListener extends AnalysisEventListener<Map<Integer, String>> {

    /**
     * 每隔3000条存储数据库，然后清理list ，方便内存回收
     */
    public static final int BATCH_COUNT = 3000;

    /**
     * 当前读取的工作表信息
     */
    private ReadSheetHolder readSheetHolder;

    /**
     * 当前读取的工作表的头部信息
     */
    private Map<Integer, String> headMap;

    /**
     * 数据回调位置
     */
    private final OperationInterface<List<Map<Integer, String>>> operationInterface;

    /**
     * 数据区: key=列数,value=值
     * 包含标题
     */
    private final List<Map<Integer, String>> list = new ArrayList<>();

    /**
     * 第一批数据
     */
    private List<Map<Integer, String>> firstList = null;

    /**
     * 当前行
     */
    private final AtomicInteger row = new AtomicInteger(0);

    public NoModelDataListener(OperationInterface<List<Map<Integer, String>>> operationInterface) {
        this.operationInterface = operationInterface;
    }

    /**
     * 每读取一行都会执行
     *
     * @param data    行数据
     * @param context 上下文
     */
    @SneakyThrows
    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        row.incrementAndGet();

        Map<Integer, String> item = new HashMap<>();
        data.forEach((key, value) -> item.put(key + 1, value));
        list.add(item);

        if (list.size() >= BATCH_COUNT) {
            if(null == firstList){
                firstList = list;
            }

            saveData();
            list.clear();
        }
    }

    /**
     * 对于每个工作表都会执行一次：这里返回第一行的内容
     *
     * @param headMap 头部
     * @param context 上下文
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        this.list.clear();

        this.readSheetHolder = context.readSheetHolder();
        this.headMap = headMap;

        invoke(headMap, context);
    }

    @SneakyThrows
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
    }

    /**
     * 加上存储数据库
     */
    private void saveData() throws Exception {
        operationInterface.make(readSheetHolder.getSheetName(), list, firstList, row);
    }
}